﻿namespace dotnet_notes.Controllers
{
    /// <summary>
    /// 登录管理
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class LoginController(SqlSugarClient db) : ControllerBase
    {
        private readonly SqlSugarClient db = db;

        /// <summary>
        /// 当前用户
        /// </summary>
        public LoginUser CurrentUser
        {
            get
            {
                return User.FindFirstValue(ClaimTypes.UserData).ToObject<LoginUser>();
            }
        }

        /// <summary>
        /// JWT 登录
        /// </summary>
        [HttpPost]
        public IActionResult JwtLogin()
        {
            var user = new LoginUser
            { 
                UserId = 1, 
                Name = "hechenyu"
            };

            JwtTool.GetToken(user.ToJson(), out string token, out DateTime tokenExpiresTime);

            if (!AppsettingsTool.RefreshJwt.ForcedLogin) // 不强制登录时生成刷新令牌的唯一标识
            {
                user.TokenId = YitIdHelper.NextId();
            }

            JwtTool.GetRefreshToken
                (user.ToJson(), out string refreshToken, out DateTime refreshTokenExpiresTime);

            var tokenInfo = new JwtTokenDto
            {
                Token = token,
                TokenExpiresTime = tokenExpiresTime,
                RefreshToken = refreshToken,
                RefreshExpiresTime = refreshTokenExpiresTime
            };

            return Ok(tokenInfo);
        }

        /// <summary>
        /// JWT 用刷新令牌换取令牌
        /// </summary>
        /// <param name="refreshToken">刷新令牌</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> JwtRefreshToken(string refreshToken)
        {
            string userData = JwtTool.ValidateRefreshToken(refreshToken);
            if (!userData.HasValue())
            {
                return Unauthorized();
            }

            var loginUser = userData.ToObject<LoginUser>();

            #region 令牌校验

            var invalidToken = await db
                .Queryable<Sys_Invalid_Token>()
                .FirstAsync(it => it.TokenId == loginUser.TokenId);

            if (invalidToken != null) // 旧刷新令牌不允许再使用
            {
                throw new InvalidOperationException(MessageConfig.InvalidToken);
            }

            var blacklist = await db
                .Queryable<Sys_User_Blacklist>()
                .FirstAsync(it => it.UserId == loginUser.UserId);

            if (blacklist != null) // 在黑名单内不允许换新令牌
            {
                throw new InvalidOperationException(MessageConfig.Blacklist);
            }

            #endregion

            long? oldTokenId = loginUser.TokenId; // 记录旧刷新令牌, 按需使其失效

            loginUser.TokenId = null;
            JwtTool.GetToken(loginUser.ToJson(), out string token, out DateTime tokenExpiresTime);

            var tokenInfo = new JwtTokenDto
            {
                Token = token,
                TokenExpiresTime = tokenExpiresTime
            };

            if (!AppsettingsTool.RefreshJwt.ForcedLogin) // 不强制登录的话每次返回新的刷新令牌
            {
                loginUser.TokenId = YitIdHelper.NextId();

                JwtTool.GetRefreshToken
                    (loginUser.ToJson(), out string newRefreshToken, out DateTime refreshTokenExpiresTime);

                tokenInfo.RefreshToken = newRefreshToken;
                tokenInfo.RefreshExpiresTime = refreshTokenExpiresTime;

                var newInvalidToken = new Sys_Invalid_Token 
                { 
                    TokenId = oldTokenId.GetValue(), 
                    CreateTime = DateTime.Now 
                };

                await db.Insertable(newInvalidToken).ExecuteCommandAsync(); // 记录旧刷新令牌, 下次不允许使用
            }

            return Ok(tokenInfo);
        }

        /// <summary>
        /// JWT 获取用户信息
        /// </summary>
        [Authorize]
        [HttpGet]
        public IActionResult JwtUserInfo()
        {
            return Ok(CurrentUser);
        }
    }
}
